package com.tspark.tspark1.zoo.filter;

import com.alibaba.fastjson2.JSONObject;
import com.tspark.tspark1.zoo.constant.MessageConstant;
import com.tspark.tspark1.zoo.properties.JwtProperties;
import com.tspark.tspark1.zoo.result.Result;
import com.tspark.tspark1.zoo.util.JwtUtil;
import com.tspark.tspark1.zoo.util.ThreadLocalUtil;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.IOException;

@WebFilter(urlPatterns = "/*")
@Slf4j
@Component
public class TokenFilter implements Filter {
    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private JwtUtil jwtUtil;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
        log.info("过滤器开启");

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse)servletResponse;
//1.获取请求url并输出到info日志
        String url = httpServletRequest.getRequestURL().toString();
        String uri = httpServletRequest.getRequestURI();//请求后缀 协议://域名"/xxx/xxx"
        log.info("收到请求 " + url + "来自" + httpServletRequest.getRemoteAddr());
//2.判断是否为根目录、登录请求或注册请求 如果是 放行
        if (uri != null && ("/".equals(uri) || uri.contains("login") || uri.contains("register"))) {
            // 放行对根目录的请求，不执行后续过滤器链
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
//3.如果不放行 获取请求头中的token
        String jwt = httpServletRequest.getHeader(jwtProperties.getTokenName());
//4.判断令牌是否存在,如果不存在返回错误结果
        if (!StringUtils.hasLength(jwt)) {
            log.info(httpServletRequest.getRemoteAddr() + "请求头中没有token!");
            Result<Object> fail = Result.fail(MessageConstant.NOT_LOGIN);
            String notLogin = JSONObject.toJSONString(fail);
            httpServletResponse.getWriter().write(notLogin);
            return;
        }
//5.令牌存在 先解析jwt 解析失败则记录日志并返回错误信息
        try {
            jwtUtil.parseClaim(jwt);
        } catch (Exception e) {
            log.info(httpServletRequest.getRemoteAddr() + "解析jwt令牌失败！");
            Result<Object> fail = Result.fail(MessageConstant.ILLEGAL_LOGIN);
            String notLogin = JSONObject.toJSONString(fail);
            httpServletResponse.getWriter().write(notLogin);
            return;
        }
//6.令牌解析成功 获取用户id 并用ThreadLocal记录
        int id = jwtUtil.getUid(jwt);
        int isAdmin = jwtUtil.isAdmin(jwt);
        //使用ThreadLocal记住当前的uid 和 身份
        ThreadLocalUtil.setCurrentId(id);
        ThreadLocalUtil.setIsAdmin(isAdmin);
//7.放行
        filterChain.doFilter(servletRequest,servletResponse);

    }


    @Override
    public void destroy() {
        Filter.super.destroy();
        log.info("过滤器关闭");
    }
}
